home *** CD-ROM | disk | FTP | other *** search
- /*
- * xcp.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * XBDY
- *
- * detection and encoding of planar boundaries in given image,
- * implementing an algorithm by C. T. Zahn [1969]
- *
- */
- #include "xcp.h"
-
-
- #define WINDOW_ROWS 3
- #define NDIRECTIONS 8
-
- #define THRESH 1
- #define MIN_POLY_SIZE 20
- #define ZERO 0
- #define ROOT2 1.414213562
-
- #define NA_MAX 128 /* lim of points, see ph.c */
-
- #define ON 1
- #define OFF 0
-
- #define RESET ON
- #define NO_RESET OFF
-
- #undef DEBUG
- #undef SHOW_CURV_PT
-
-
- /* global variables */
- extern short tiffInput; /* flag=0 if no ImageIn to set tags; else =1 */
- struct curv_points *curv_head_in[NDIRECTIONS];
- struct curv_points *curv_head_out[NDIRECTIONS];
- struct curv_points *curv_tail_in[NDIRECTIONS];
- struct curv_points *curv_tail_out[NDIRECTIONS];
-
- struct polygon *poly_head_ptr;
- struct polygon *poly_tail_ptr;
- float *delta_phik, *delta_lk;
-
- long ncp = 0;
-
- int loop_switch = ON; /* enable/disable loop for polyg. approx */
- int hull_switch = ON; /* enable/disable eval of convex hull */
- int n_ap_max = NA_MAX; /* max no allowed vertices in approx. poly */
-
- extern char *optarg;
- extern int optind, opterr;
- char *in_filename;
-
- /*
- * usage of routine
- */
- void
- usage (char *progname)
- {
- progname = last_bs (progname);
- printf ("USAGE: %s inimg [-L]\n", progname);
- printf ("\n%s detects and encodes contours, or planar boundaries, of regions\n", progname);
- printf ("in a binary image implementing an algorithm by C. T. Zahn [1969]\n\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: input image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -L: print Software License for this module\n");
-
- exit (1);
- }
-
- void
- init_structs ()
- {
- int m;
-
- for (m = 0; m < NDIRECTIONS; m++) {
- curv_tail_in[m] = curv_tail_out[m] = NULL;
- curv_head_in[m] = curv_head_out[m] = NULL;
- }
- poly_head_ptr = NULL;
- poly_tail_ptr = NULL;
- }
-
- /*
- * acquire first three rows from input image
- * and transfer them to the window
- */
- void
- xfer_first_3_rows (unsigned char *window[], Image * imgIO)
- {
- int ir;
-
- for (ir = 0; ir < 3; ir++)
- getrow (*(window + ir), ir, imgIO);
- }
-
- /*
- * acquire next from input image
- * and transfer it to the window
- */
- void
- xfer_next_row (unsigned char *window[], int ir, Image * imgIO)
- {
- int y;
- unsigned char *char_ptr;
-
- char_ptr = *(window + (ir % WINDOW_ROWS));
- y = ir + 3; /* offset of 3 from first_3_rows */
- getrow (char_ptr, y, imgIO);
- }
-
- /*
- * zero border error message
- */
- void
- border_err (int row, int col)
- {
- printf ("...AOI border not zeroed at row %d, col %d\n", row, col);
- exit (1);
- }
-
- /*
- * image border must be zeroed -- check it!
- */
- void
- check_border (unsigned char *window[], int ir, int jmax, int imax, Image * imgIO)
- {
- int jc;
- unsigned char *char_ptr;
-
- if (ir == 0) {
- char_ptr = *(window + (ir % WINDOW_ROWS));
- for (jc = 0; jc < jmax; jc++)
- if (*(char_ptr + jc) != ZERO)
- border_err (ir, jc);
- }
- if (ir == (imax - WINDOW_ROWS)) {
- char_ptr = *(window + ((ir + 0) % WINDOW_ROWS));
- if (*(char_ptr) != ZERO)
- border_err (ir, 0);
- if (*(char_ptr + (jmax - 1)) != ZERO)
- border_err (ir, jmax - 1);
-
- char_ptr = *(window + ((ir + 1) % WINDOW_ROWS));
- if (*(char_ptr) != ZERO)
- border_err (ir + 1, 0);
- if (*(char_ptr + (jmax - 1)) != ZERO)
- border_err (ir + 1, jmax - 1);
-
- char_ptr = *(window + ((ir + 2) % WINDOW_ROWS));
- for (jc = 0; jc < jmax; jc++)
- if (*(char_ptr + jc) != ZERO)
- border_err (ir + 2, jc);
- }
- else {
- char_ptr = *(window + (ir % WINDOW_ROWS));
- if (*(char_ptr) != ZERO)
- border_err (ir, 0);
- if (*(char_ptr + (jmax - 1)) != ZERO)
- border_err (ir, jmax - 1);
- }
- }
-
- /*
- * memory allocation for image (one row at a time)
- */
- int
- img_alloc (unsigned char *img[], int nr, int nc)
- {
- int ir;
-
- for (ir = 0; ir < nr; ir++) {
- if ((*(img + ir) = (unsigned char *) calloc (nc, sizeof (unsigned char))) == NULL)
- return (0);
- else
- *(img + ir) += 0;
-
- }
- return (1);
- }
-
-
- void
- main (int argc, char *argv[])
- {
- unsigned char *window[WINDOW_ROWS];
- int ir;
- int nr, nc;
- int jmin, imin, jmax, imax;
- int left_x, right_x;
- float *delta_phikp, *delta_lkp;
- Image *imgIn; /* input image */
- Image *imgOut = NULL; /* output image not (used in this program) */
- int i_arg;
-
- /*
- * cmd line options
- */
- static char *optstring = "c:bL";
-
-
- /*
- * parse command line
- */
- optind = 2; /* set getopt to point to the 3rd arg */
- opterr = ON; /* give error messages */
-
-
- if (argc < 2)
- usage (argv[0]);
-
- while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
- switch (i_arg) {
- case 'L':
- print_sos_lic ();
- exit (0);
- default:
- printf ("\ngetopt: unknown condition encountered\n");
- exit (1);
- break;
- }
- }
- /*
- * initialize structures
- */
- init_structs ();
-
- /*
- * get the input image
- */
- imgIn = ImageIn (argv[1]);
- if (imgIn->bps == 8 && imgIn->spp == 3) {
- printf ("Got RGB image!!!\n");
- fprintf (stderr, "Can only work with Grayscale or Binary TIFF files!!!\n");
- exit (1);
- }
- in_filename = argv[1];
-
- jmin = imin = 0;
- jmax = imgIn->width;
- imax = imgIn->height;
-
- left_x = jmin;
- right_x = jmax - 1;
- nc = jmax - jmin;
- nr = imax - imin;
-
- #ifdef DEBUG
- printf ("\n...nc = %d, nr = %d\n", nc, nr);
- #endif
-
- /*
- * zero outer border of image
- */
- zero_border (imgIn, 2);
-
- /*
- * allocate memory
- */
- if ((img_alloc (window, WINDOW_ROWS, nc) == 0))
- exitmess ("window", 1);
-
- printf ("\n...scan image...\n");
- xfer_first_3_rows (window, imgIn);
- for (ir = 0; ir < imax - WINDOW_ROWS; ir++) {
- check_border (window, ir, jmax, imax, imgIn);
- curvature_points (window, ir, jmax, imax);
- xfer_next_row (window, ir, imgIn);
- }
- check_border (window, ir, jmax, imax, imgIn);
- curvature_points (window, ir, jmax, imax);
-
-
- if ((delta_phikp = (float *) calloc (ncp, sizeof (float))) == NULL)
- exitmess ("delta_phik", 1);
- if ((delta_lkp = (float *) calloc (ncp, sizeof (float))) == NULL)
- exitmess ("delta_phik", 1);
- delta_phik = delta_phikp;
- delta_lk = delta_lkp;
-
- /*
- * construct lists representing individual boundaries
- */
- printf ("...construct linked lists of boundary points...\n");
- linkage (imgIn, imgOut, WHITE);
-
- free (delta_phikp);
- free (delta_lkp);
- }
-